﻿LRC = function() {
	this.initialize.apply(this, arguments)
};
LRC.prototype = {
	arrLyricTime: [],
	arrLyric: [],
	initialize: function(arg) {
		this.lyricWrapper = arg.lyricWrapper;
		this.curRowClassName = arg.curRowClassName;
		this.separator = arg.separator;
		this.wordTime = -1;
		this.arrLyricTime = [];
		this.arrLyric = [];
		this.initArray(arg.lyric);
		this.arrLyricTime = this.sort(this.arrLyricTime);
		this.setLyricTable(this.arrLyric)
	},
	initArray: function(lyric) {
		var lrc_re = new RegExp('\[[0-9:.]*\]', 'g');
		var lrc_arr = lyric.split(this.separator);
		var lrc_temp = 0;
		var lrc_filter = 0;
		for (var i = 0; i < lrc_arr.length; i++) {
			var lrc_txt = lrc_arr[i].replace(/\[[\w\W]*\]/g, '').Trim();
			if (lrc_txt == '') {
				lrc_filter++;
				continue
			}
			this.arrLyric[i - lrc_filter] = lrc_txt;
			while ((lrc_result = lrc_re.exec(lrc_arr[i])) != null) {
				var lrc_second = this.parseSecond(lrc_result.toString().replace(/\[|\]/g, ''));
				if (!isNaN(lrc_second)) this.arrLyricTime[lrc_temp++] = (i - lrc_filter) + '|' + lrc_second
			}
		}
	},
	IsLyricValid: function(arrLyricTime) {
		return this.arrLyricTime.length > 0
	},
	DoSync: function(curPosition) {
		clearInterval(this.wordTime);
		var lrc_times = this.arrLyricTime;
		for (var i = 0; i < lrc_times.length; i++) {
			var lrc_arrPre = lrc_times[i].split('|');
			if (i == 0 && curPosition < lrc_arrPre[1]) break;
			if (lrc_times[i + 1] == undefined) {
				this.setRow(lrc_arrPre[0]);
				break
			}
			var lrc_arrNext = lrc_times[i + 1].split('|');
			if (curPosition >= lrc_arrPre[1] && curPosition < lrc_arrNext[1]) {
				this.setRow(lrc_arrPre[0]);
				break
			}
		}
	},
	parseSecond: function(time) {
		try {
			var lrc_arr = time.split(':');
			return parseInt(lrc_arr[0], 10) * 60 + parseFloat(lrc_arr[1])
		} catch (ex) {
			return 0
		}
	},
	setLyricTable: function(arrLyric) {
		var html = "";
		this.lyricWrapper.scrollTop = 0;
		this.lyricWrapper.innerHTML = "";
		for (var i = 0; i < arrLyric.length; i++) {
			html += "<p>" + arrLyric[i] + "</p>"
		}
		this.lyricWrapper.innerHTML = html
	},
	setRow: function(index) {
		this.setRowClass(index);
		this.setScroll(index)
	},
	setRowClass: function(index) {
		var lrc_rows = this.lyricWrapper.getElementsByTagName("p");
		for (var i = 0; i < lrc_rows.length; i++) {
			lrc_rows[i].className = ''
		}
		lrc_rows[index].className = this.curRowClassName;
		if (lrc_rows[index].scrollWidth > lrc_rows[index].offsetWidth) {
			this.wordTime = setInterval(function() {
				lrc_rows[index].scrollLeft++
			}, 50)
		}
	},
	setScroll: function(index) {
		var lrc_rows = this.lyricWrapper.getElementsByTagName("p");
		this.lyricWrapper.scrollTop = lrc_rows[index].offsetTop - Math.round(this.lyricWrapper.offsetHeight / 3)
	},
	sort: function(arrLyricTime) {
		for (var i = 0; i < arrLyricTime.length - 1; i++) {
			for (var ii = i + 1; ii < arrLyricTime.length; ii++) {
				var lrc_cur = parseFloat(arrLyricTime[i].split('|')[1]);
				var lrc_next = parseFloat(arrLyricTime[ii].split('|')[1]);
				if (lrc_cur > lrc_next) {
					var lrc_temp = arrLyricTime[i];
					arrLyricTime[i] = arrLyricTime[ii];
					arrLyricTime[ii] = lrc_temp
				}
			}
		}
		return arrLyricTime
	}
};
String.prototype.Trim = function() {
	return this.replace(/^\s*|\s*$/g, "")
};

function Swipe(container, options) {
	"use strict";
	var noop = function() {};
	var offloadFn = function(fn) {
			setTimeout(fn || noop, 0)
		};
	var browser = {
		addEventListener: !! window.addEventListener,
		touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
		transitions: (function(temp) {
			var props = ['transitionProperty', 'WebkitTransition', 'MozTransition', 'OTransition', 'msTransition'];
			for (var i in props) if (temp.style[props[i]] !== undefined) return true;
			return false
		})(document.createElement('swipe'))
	};
	if (!container) return;
	var element = container.children[0];
	var slides, slidePos, width, length;
	options = options || {};
	var index = parseInt(options.startSlide, 10) || 0;
	var speed = options.speed || 300;
	options.continuous = options.continuous !== undefined ? options.continuous : true;

	function setup() {
		slides = element.children;
		length = slides.length;
		if (slides.length < 2) options.continuous = false;
		if (browser.transitions && options.continuous && slides.length < 3) {
			element.appendChild(slides[0].cloneNode(true));
			element.appendChild(element.children[1].cloneNode(true));
			slides = element.children
		}
		slidePos = new Array(slides.length);
		width = container.getBoundingClientRect().width || container.offsetWidth;
		element.style.width = (slides.length * width) + 'px';
		var pos = slides.length;
		while (pos--) {
			var slide = slides[pos];
			slide.style.width = width + 'px';
			slide.setAttribute('data-index', pos);
			if (browser.transitions) {
				slide.style.left = (pos * -width) + 'px';
				move(pos, index > pos ? -width : (index < pos ? width : 0), 0)
			}
		}
		if (options.continuous && browser.transitions) {
			move(circle(index - 1), -width, 0);
			move(circle(index + 1), width, 0)
		}
		if (!browser.transitions) element.style.left = (index * -width) + 'px';
		container.style.visibility = 'visible'
	}
	function prev() {
		if (options.continuous) slide(index - 1);
		else if (index) slide(index - 1)
	}
	function next() {
		if (options.continuous) slide(index + 1);
		else if (index < slides.length - 1) slide(index + 1)
	}
	function circle(index) {
		return (slides.length + (index % slides.length)) % slides.length
	}
	function slide(to, slideSpeed) {
		if (index == to) return;
		if (browser.transitions) {
			var direction = Math.abs(index - to) / (index - to);
			if (options.continuous) {
				var natural_direction = direction;
				direction = -slidePos[circle(to)] / width;
				if (direction !== natural_direction) to = -direction * slides.length + to
			}
			var diff = Math.abs(index - to) - 1;
			while (diff--) move(circle((to > index ? to : index) - diff - 1), width * direction, 0);
			to = circle(to);
			move(index, width * direction, slideSpeed || speed);
			move(to, 0, slideSpeed || speed);
			if (options.continuous) move(circle(to - direction), -(width * direction), 0)
		} else {
			to = circle(to);
			animate(index * -width, to * -width, slideSpeed || speed)
		}
		index = to;
		offloadFn(options.callback && options.callback(index, slides[index]))
	}
	function move(index, dist, speed) {
		translate(index, dist, speed);
		slidePos[index] = dist
	}
	function translate(index, dist, speed) {
		var slide = slides[index];
		var style = slide && slide.style;
		if (!style) return;
		style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = speed + 'ms';
		style.webkitTransform = 'translate(' + dist + 'px,0)translateZ(0)';
		style.msTransform = style.MozTransform = style.OTransform = 'translateX(' + dist + 'px)'
	}
	function animate(from, to, speed) {
		if (!speed) {
			element.style.left = to + 'px';
			return
		}
		var start = +new Date;
		var timer = setInterval(function() {
			var timeElap = +new Date - start;
			if (timeElap > speed) {
				element.style.left = to + 'px';
				if (delay) begin();
				options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);
				clearInterval(timer);
				return
			}
			element.style.left = (((to - from) * (Math.floor((timeElap / speed) * 100) / 100)) + from) + 'px'
		}, 4)
	}
	var delay = options.auto || 0;
	var interval;

	function begin() {
		interval = setTimeout(next, delay)
	}
	function stop() {
		clearTimeout(interval)
	}
	var start = {};
	var delta = {};
	var isScrolling;
	var events = {
		handleEvent: function(event) {
			switch (event.type) {
			case 'touchstart':
				this.start(event);
				break;
			case 'touchmove':
				this.move(event);
				break;
			case 'touchend':
				offloadFn(this.end(event));
				break;
			case 'webkitTransitionEnd':
			case 'msTransitionEnd':
			case 'oTransitionEnd':
			case 'otransitionend':
			case 'transitionend':
				offloadFn(this.transitionEnd(event));
				break;
			case 'resize':
				offloadFn(setup.call());
				break
			}
			if (options.stopPropagation) event.stopPropagation()
		},
		start: function(event) {
			var touches = event.touches[0];
			start = {
				x: touches.pageX,
				y: touches.pageY,
				time: +new Date
			};
			isScrolling = undefined;
			delta = {};
			element.addEventListener('touchmove', this, false);
			element.addEventListener('touchend', this, false)
		},
		move: function(event) {
			if (event.touches.length > 1 || event.scale && event.scale !== 1) return;
			if (options.disableScroll) event.preventDefault();
			var touches = event.touches[0];
			delta = {
				x: touches.pageX - start.x,
				y: touches.pageY - start.y
			};
			if (typeof isScrolling == 'undefined') {
				isScrolling = !! (isScrolling || Math.abs(delta.x) < Math.abs(delta.y))
			}
			if (!isScrolling) {
				event.preventDefault();
				stop();
				if (options.continuous) {
					translate(circle(index - 1), delta.x + slidePos[circle(index - 1)], 0);
					translate(index, delta.x + slidePos[index], 0);
					translate(circle(index + 1), delta.x + slidePos[circle(index + 1)], 0)
				} else {
					delta.x = delta.x / ((!index && delta.x > 0 || index == slides.length - 1 && delta.x < 0) ? (Math.abs(delta.x) / width + 1) : 1);
					translate(index - 1, delta.x + slidePos[index - 1], 0);
					translate(index, delta.x + slidePos[index], 0);
					translate(index + 1, delta.x + slidePos[index + 1], 0)
				}
			}
		},
		end: function(event) {
			var duration = +new Date - start.time;
			var isValidSlide = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > width / 2;
			var isPastBounds = !index && delta.x > 0 || index == slides.length - 1 && delta.x < 0;
			if (options.continuous) isPastBounds = false;
			var direction = delta.x < 0;
			if (!isScrolling) {
				if (isValidSlide && !isPastBounds) {
					if (direction) {
						if (options.continuous) {
							move(circle(index - 1), -width, 0);
							move(circle(index + 2), width, 0)
						} else {
							move(index - 1, -width, 0)
						}
						move(index, slidePos[index] - width, speed);
						move(circle(index + 1), slidePos[circle(index + 1)] - width, speed);
						index = circle(index + 1)
					} else {
						if (options.continuous) {
							move(circle(index + 1), width, 0);
							move(circle(index - 2), -width, 0)
						} else {
							move(index + 1, width, 0)
						}
						move(index, slidePos[index] + width, speed);
						move(circle(index - 1), slidePos[circle(index - 1)] + width, speed);
						index = circle(index - 1)
					}
					options.callback && options.callback(index, slides[index])
				} else {
					if (options.continuous) {
						move(circle(index - 1), -width, speed);
						move(index, 0, speed);
						move(circle(index + 1), width, speed)
					} else {
						move(index - 1, -width, speed);
						move(index, 0, speed);
						move(index + 1, width, speed)
					}
				}
			}
			element.removeEventListener('touchmove', events, false);
			element.removeEventListener('touchend', events, false)
		},
		transitionEnd: function(event) {
			if (parseInt(event.target.getAttribute('data-index'), 10) == index) {
				if (delay) begin();
				options.transitionEnd && options.transitionEnd.call(event, index, slides[index])
			}
		}
	};
	setup();
	if (delay) begin();
	if (browser.addEventListener) {
		if (browser.touch) element.addEventListener('touchstart', events, false);
		if (browser.transitions) {
			element.addEventListener('webkitTransitionEnd', events, false);
			element.addEventListener('msTransitionEnd', events, false);
			element.addEventListener('oTransitionEnd', events, false);
			element.addEventListener('otransitionend', events, false);
			element.addEventListener('transitionend', events, false)
		}
		window.addEventListener('resize', events, false)
	} else {
		window.onresize = function() {
			setup()
		}
	}
	return {
		setup: function() {
			setup()
		},
		slide: function(to, speed) {
			stop();
			slide(to, speed)
		},
		prev: function() {
			stop();
			prev()
		},
		next: function() {
			stop();
			next()
		},
		getPos: function() {
			return index
		},
		getNumSlides: function() {
			return length
		},
		kill: function() {
			stop();
			element.style.width = 'auto';
			element.style.left = 0;
			var pos = slides.length;
			while (pos--) {
				var slide = slides[pos];
				slide.style.width = '100%';
				slide.style.left = 0;
				if (browser.transitions) translate(pos, 0, 0)
			}
			if (browser.addEventListener) {
				element.removeEventListener('touchstart', events, false);
				element.removeEventListener('webkitTransitionEnd', events, false);
				element.removeEventListener('msTransitionEnd', events, false);
				element.removeEventListener('oTransitionEnd', events, false);
				element.removeEventListener('otransitionend', events, false);
				element.removeEventListener('transitionend', events, false);
				window.removeEventListener('resize', events, false)
			} else {
				window.onresize = null
			}
		}
	}
}
if (window.jQuery || window.Zepto) {
	(function($) {
		$.fn.Swipe = function(params) {
			return this.each(function() {
				$(this).data('Swipe', new Swipe($(this)[0], params))
			})
		}
	})(window.jQuery || window.Zepto)
}(function($) {
	$.matchMedia = (function() {
		var mediaId = 0,
			cls = 'gmu-media-detect',
			transitionEnd = $.fx.transitionEnd,
			cssPrefix = $.fx.cssPrefix,
			$style = $('<style></style>').append('.' + cls + '{' + cssPrefix + 'transition: width 0.001ms; width: 0; position: absolute; top: -10000px;}\n').appendTo('head');
		return function(query) {
			var id = cls + mediaId++,
				$mediaElem, listeners = [],
				ret;
			$style.append('@media ' + query + ' { #' + id + ' { width: 1px; } }\n');
			if ('matchMedia' in window) {
				return window.matchMedia(query)
			}
			$mediaElem = $('<div class="' + cls + '" id="' + id + '"></div>').appendTo('body').on(transitionEnd, function() {
				ret.matches = $mediaElem.width() === 1;
				$.each(listeners, function(i, fn) {
					$.isFunction(fn) && fn.call(ret, ret)
				})
			});
			ret = {
				matches: $mediaElem.width() === 1,
				media: query,
				addListener: function(callback) {
					listeners.push(callback);
					return this
				},
				removeListener: function(callback) {
					var index = listeners.indexOf(callback);~index && listeners.splice(index, 1);
					return this
				}
			};
			return ret
		}
	}())
})(Zepto);
$(function() {
	$.mediaQuery = {
		ortchange: 'screen and (width: ' + window.innerWidth + 'px)'
	};
	$.matchMedia($.mediaQuery.ortchange).addListener(function() {
		$(window).trigger('ortchange')
	})
});
(function($) {
	$.extend($, {
		throttle: function(delay, fn, debounce_mode) {
			var last = 0,
				timeId;
			if (typeof fn !== 'function') {
				debounce_mode = fn;
				fn = delay;
				delay = 250
			}
			function wrapper() {
				var that = this,
					period = Date.now() - last,
					args = arguments;

				function exec() {
					last = Date.now();
					fn.apply(that, args)
				}
				function clear() {
					timeId = undefined
				}
				if (debounce_mode && !timeId) {
					exec()
				}
				timeId && clearTimeout(timeId);
				if (debounce_mode === undefined && period > delay) {
					exec()
				} else {
					timeId = setTimeout(debounce_mode ? clear : exec, debounce_mode === undefined ? delay - period : delay)
				}
			}
			wrapper._zid = fn._zid = fn._zid || $.proxy(fn)._zid;
			return wrapper
		},
		debounce: function(delay, fn, t) {
			return fn === undefined ? $.throttle(250, delay, false) : $.throttle(delay, fn, t === undefined ? false : t !== false)
		}
	})
})(Zepto);
(function($, win) {
	function registerScrollStop() {
		$(win).on('scroll', $.debounce(80, function() {
			$(win).trigger('scrollStop')
		}, false))
	}
	function backEventOffHandler() {
		$(win).off('scroll');
		registerScrollStop()
	}
	registerScrollStop();
	$(win).on('pageshow', function(e) {
		e.persisted && $(win).off('touchstart', backEventOffHandler).one('touchstart', backEventOffHandler)
	})
})(Zepto, window);
(function($) {
	var pedding = [];
	$.fn.imglazyload = function(opts) {
		var splice = Array.prototype.splice,
			opts = $.extend({
				threshold: 0,
				container: window,
				urlName: 'data-url',
				placeHolder: '',
				eventName: 'scrollStop',
				innerScroll: false,
				isVertical: true
			}, opts),
			$viewPort = $(opts.container),
			isVertical = opts.isVertical,
			isWindow = $.isWindow($viewPort.get(0)),
			OFFSET = {
				win: [isVertical ? 'scrollY' : 'scrollX', isVertical ? 'innerHeight' : 'innerWidth'],
				img: [isVertical ? 'top' : 'left', isVertical ? 'height' : 'width']
			},
			$plsHolder = $(opts.placeHolder).length ? $(opts.placeHolder) : null,
			isImg = $(this).is('img');
		!isWindow && (OFFSET['win'] = OFFSET['img']);

		function isInViewport(offset) {
			var viewOffset = isWindow ? window : $viewPort.offset(),
				viewTop = viewOffset[OFFSET.win[0]],
				viewHeight = viewOffset[OFFSET.win[1]];
			return viewTop >= offset[OFFSET.img[0]] - opts.threshold - viewHeight && viewTop <= offset[OFFSET.img[0]] + offset[OFFSET.img[1]]
		}
		pedding = Array.prototype.slice.call($(pedding.reverse()).add(this), 0).reverse();
		if ($.isFunction($.fn.imglazyload.detect)) {
			_addPlsHolder();
			return this
		}
		function _load(div) {
			var $div = $(div),
				attrObj = {},
				$img = $div;
			if (!isImg) {
				$.each($div.get(0).attributes, function() {~this.name.indexOf('data-') && (attrObj[this.name] = this.value)
				});
				$img = $('<img />').attr(attrObj)
			}
			$div.trigger('startload');
			$img.on('load', function() {
				!isImg && $div.replaceWith($img);
				$div.trigger('loadcomplete');
				$img.off('load')
			}).on('error', function() {
				var errorEvent = $.Event('error');
				$div.trigger(errorEvent);
				errorEvent.defaultPrevented || pedding.push(div);
				$img.off('error').remove()
			}).attr('src', $div.attr(opts.urlName))
		}
		function _detect() {
			var i, $image, offset, div;
			for (i = pedding.length; i--;) {
				$image = $(div = pedding[i]);
				offset = $image.offset();
				isInViewport(offset) && (splice.call(pedding, i, 1), _load(div))
			}
		}
		function _addPlsHolder() {
			!isImg && $plsHolder && $(pedding).append($plsHolder)
		}
		$(document).ready(function() {
			_addPlsHolder();
			_detect()
		});
		!opts.innerScroll && $(window).on(opts.eventName + ' ortchange', function() {
			_detect()
		});
		$.fn.imglazyload.detect = _detect;
		return this
	}
})(Zepto);
(function($, undefined) {
	$.extend($.fn, {
		fix: function(opts) {
			var me = this;
			if (me.attr('isFixed')) return me;
			me.css(opts).css('position', 'fixed').attr('isFixed', true);
			var buff = $('<div style="position:fixed;top:10px;"></div>').appendTo('body'),
				top = buff[0].getBoundingClientRect().top,
				checkFixed = function() {
					if (window.pageYOffset > 0) {
						if (buff[0].getBoundingClientRect().top !== top) {
							me.css('position', 'absolute');
							doFixed();
							$(window).on('scrollStop', doFixed);
							$(window).on('ortchange', doFixed)
						}
						$(window).off('scrollStop', checkFixed);
						buff.remove()
					}
				},
				doFixed = function() {
					me.css({
						top: window.pageYOffset + (opts.bottom !== undefined ? window.innerHeight - me.height() - opts.bottom : (opts.top || 0)),
						left: opts.right !== undefined ? document.body.offsetWidth - me.width() - opts.right : (opts.left || 0)
					});
					opts.width == '100%' && me.css('width', document.body.offsetWidth)
				};
			$(window).on('scrollStop', checkFixed);
			return me
		}
	})
}(Zepto));